﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Security.Policy;
using UnityEngine;
using ZLMsg;
using static UnityEngine.Networking.UnityWebRequest;

namespace ZL_Framework
{
    /// <summary>
    /// 资源更新
    /// </summary>
    public class ResourceUpdateManager : MonoSingleton<ResourceUpdateManager>, IMsgSender
    {
        private string fileListPath;
        private Dictionary<string, ResFileInfo> localResFilesDic = new Dictionary<string, ResFileInfo>();
        private Dictionary<string, ResFileInfo> serverResFilesDic = new Dictionary<string, ResFileInfo>();
        private Dictionary<string, ResFileInfo> needUpdateResFilesDic = new Dictionary<string, ResFileInfo>();

        private Action<long> updateStart;
        private Action updateComplete;
        private Action<float> updateProgress;
        //private string RemoteURL = "http://localhost:1313/Res/ZLF_Res/";

        protected override void Init()
        {
            fileListPath = AppConfig.Instance.ABPath + "/files.txt";
        }

        protected override void Destroy()
        {
            localResFilesDic?.Clear();
            serverResFilesDic?.Clear();
            needUpdateResFilesDic?.Clear();
            updateStart = null;
            updateComplete = null;
            updateProgress = null;
        }

        /// <summary>
        /// 开始更新资源
        /// </summary>
        public void StartUpdateRes(Action<long> _updateStart, Action _updateEnd, Action<float> _updateProgress)
        {
            updateStart = _updateStart;
            updateComplete = _updateEnd;
            updateProgress = _updateProgress;
            if (AppConfig.Instance.Config.PlayMode == PlayMode.SimulateLoad)
            {
                Debug.Log("当前资源为虚拟加载，不需要更新");
                updateStart?.Invoke(0);
                updateComplete?.Invoke();
                return;
            }

            if (File.Exists(fileListPath))
            {
                ParseLocalFileList();
                DownloadServerResFilesList(() =>
                {
                    CheckNeedUpdateResList();
                    DownloadRes();
                });
            }
            else
            {
                Debug.Log("没有获取到资源列表文件，开始下载服务器资源！");
                DownloadServerResFilesList(() =>
                {
                    needUpdateResFilesDic = serverResFilesDic;
                    DownloadRes();
                });
            }
        }

        /// <summary>
        /// 解析本地资源文件列表
        /// </summary>
        private void ParseLocalFileList()
        {
            string[] local_files = File.ReadAllLines(fileListPath);
            for (int i = 0; i < local_files.Length; i++)
            {
                string curFile = local_files[i].Trim();
                if (!string.IsNullOrEmpty(curFile))
                {
                    string[] value = curFile.Split('|');
                    ResFileInfo resFileInfo = new ResFileInfo
                    {
                        resName = value[0].Trim(),
                        resMD5 = value[1].Trim(),
                        resSize = long.Parse(value[2].Trim())
                    };
                    localResFilesDic.Add(resFileInfo.resName, resFileInfo);
                }
            }
        }

        /// <summary>
        /// 获取服务器资源文件列表
        /// </summary>
        private void DownloadServerResFilesList(Action action)
        {
            //从服务器获取资源列表文件
            HttpRequestManager.Instance.Get(AppConfig.Instance.Config.RemoteResLoadUrl + "files.txt", (result) =>
             {
                 SaveFile(result.downloadHandler.data, fileListPath);

                 string serverFiles = result.downloadHandler.text.Trim();

                 string[] files = serverFiles.Split('\n');
                 for (int i = 0; i < files.Length; i++)
                 {
                     string curFile = files[i].Trim();
                     if (!string.IsNullOrEmpty(curFile))
                     {
                         string[] value = curFile.Split('|');
                         ResFileInfo resFileInfo = new ResFileInfo
                         {
                             resName = value[0].Trim(),
                             resMD5 = value[1].Trim(),
                             resSize = long.Parse(value[2].Trim())
                         };
                         serverResFilesDic.Add(resFileInfo.resName, resFileInfo);
                     }
                 }
                 action?.Invoke();
             });
        }

        private void SaveFile(byte[] data, string path)
        {
            if (!Directory.Exists(AppConfig.Instance.ABPath))
            {
                Directory.CreateDirectory(AppConfig.Instance.ABPath);
            }
            string ab_path = Path.Combine(AppConfig.Instance.ABPath, "assetbundle");
            if (!Directory.Exists(ab_path))
            {
                Directory.CreateDirectory(ab_path);
            }
            string lua_path = Path.Combine(AppConfig.Instance.ABPath, "luascripts");
            if (!Directory.Exists(lua_path))
            {
                Directory.CreateDirectory(lua_path);
            }
            File.WriteAllBytes(path, data);
        }

        /// <summary>
        /// 检查需要更新的资源
        /// </summary>
        private void CheckNeedUpdateResList()
        {
            if (serverResFilesDic.Count > 0)
            {
                foreach (string serverResName in serverResFilesDic.Keys)
                {
                    ResFileInfo serverRes = serverResFilesDic[serverResName];
                    if (localResFilesDic.ContainsKey(serverResName))
                    {
                        ResFileInfo localRes = localResFilesDic[serverResName];
                        //比较本地和服务器资源的MD5码，不同就下载
                        if (!string.Equals(serverRes.resMD5, localRes.resMD5))
                        {
                            needUpdateResFilesDic.Add(serverResName, serverRes);
                        }
                    }
                    else    //如果本地没有就直接下载
                    {
                        needUpdateResFilesDic.Add(serverResName, serverRes);
                    }
                }
            }
        }

        /// <summary>
        /// 获取需要下载的资源大小
        /// </summary>
        /// <returns></returns>
        private long GetNeedUpdateSize()
        {
            long size = 0;
            if (needUpdateResFilesDic.Count > 0)
            {
                foreach (var item in needUpdateResFilesDic.Values)
                {
                    size += item.resSize;
                }
            }
            return size;
        }

        /// <summary>
        /// 开始下载资源
        /// </summary>
        private async void DownloadRes()
        {
            long resSize = GetNeedUpdateSize();
            updateStart?.Invoke(resSize);
            if (resSize > 0)
            {
                int download_index = 0;
                //TODO这里处理具体下载的逻辑
                //全部更新完毕之后调用 ResUpdateComplete()
                foreach (var item in needUpdateResFilesDic)
                {
                    var result = await HttpRequestManager.Instance.Get(AppConfig.Instance.Config.RemoteResLoadUrl + item.Value.resName);
                    download_index++;
                    string filePath = Path.Combine(AppConfig.Instance.ABPath, item.Value.resName);
                    if (result.result == Result.Success)
                    {
                        SaveFile(result.downloadHandler.data, filePath);
                        updateProgress?.Invoke((float)download_index / needUpdateResFilesDic.Count);
                    }
                }
                Debug.Log("资源更新完成");
                ResUpdateComplete();
                updateComplete?.Invoke();
            }
            else
            {
                Debug.Log("没有需要更新的资源");
                updateComplete?.Invoke();
            }
        }

        private void ResUpdateComplete()
        {
            this.SendLogicMsg(MsgName.MSG_RES_UPDATE_END);
        }
    }

    public class ResFileInfo
    {
        /// <summary>
        /// 资源名称
        /// </summary>
        public string resName;
        /// <summary>
        /// MD5
        /// </summary>
        public string resMD5;
        /// <summary>
        /// 文件大小
        /// </summary>
        public long resSize;
    }
}